﻿//
// *************************************************************************************
// WP-Framework
// 
// Developed by
// Lukas Kretschmar (lkretschmar.dev@bluewin.ch)
//
// Switzerland, Copyright (c) 2013 lkretschmar
// This content is released under the MIT License (http://opensource.org/licenses/MIT).
//     
// *************************************************************************************
//
//



using Microsoft.VisualStudio.TestTools.UnitTesting;
using KretschIT.WP_Fx.EasyMoq.Generator.Arguments;
using KretschIT.WP_Fx.EasyMoq.Generator.Tests.Helpers.Objects;
using System.Reflection;
using System.Linq;
using System;
using KretschIT.WP_Fx.EasyMoq.Generator.Items;
using System.Collections.Generic;

namespace KretschIT.WP_Fx.EasyMoq.Generator.Tests.Arguments
{
    [TestClass]
    public class ParameterArgumentBuilderTest
    {
        private IParameterArgumentBuilder builder;

        [TestInitialize]
        public void Init()
        {
            var nameFactory = new NamingFactory(new List<Type> { typeof(IEnumerable<>) });
            this.builder = new ParameterArgumentBuilder(nameFactory);
        }

        [TestMethod]
        public void Test_NonArgument()
        {
            Assert.AreEqual(string.Empty, this.builder.String);

            this.builder.Add(null, true);

            Assert.AreEqual(string.Empty, this.builder.String);
        }

        [TestMethod]
        public void Test_SimpleArgument()
        {
            var type = typeof(ITestObject);
            var method = type.GetMethod("Action", new Type[] { typeof(string) });

            this.builder.Add(method.GetParameters().Single(), false);

            Assert.AreEqual("arg", this.builder.String);
        }

        [TestMethod]
        public void Test_SimpleArgument_WithType()
        {
            var type = typeof(ITestObject);
            var method = type.GetMethod("Action", new Type[] { typeof(string) });

            this.builder.Add(method.GetParameters().Single(), true);

            Assert.AreEqual("System.String arg", this.builder.String);
        }

        [TestMethod]
        public void Test_MultipleArgument()
        {
            var type = typeof(ITestObject);
            var method = type.GetMethod("Action", new Type[] { typeof(string), typeof(string) });

            foreach(var p in method.GetParameters())
            {
                this.builder.Add(p, false);
            }

            Assert.AreEqual("first, second", this.builder.String);
        }

        [TestMethod]
        public void Test_MultipleArgument_WithTypes()
        {
            var type = typeof(ITestObject);
            var method = type.GetMethod("Action", new Type[] { typeof(string), typeof(string) });

            foreach (var p in method.GetParameters())
            {
                this.builder.Add(p, true);
            }

            Assert.AreEqual("System.String first, System.String second", this.builder.String);
        }

        [TestMethod]
        public void Test_GenericArgumnt()
        {
            var type = typeof(ITestGenericMethod);
            var method = type.GetMethod("GenericArgument");

            this.builder.Add(method.GetParameters().Single(), false);

            Assert.AreEqual("arg", this.builder.String);
        }

        [TestMethod]
        public void Test_GenericArgument_WithType()
        {
            var type = typeof(ITestGenericMethod);
            var method = type.GetMethod("GenericArgument");

            this.builder.Add(method.GetParameters().Single(), true);

            Assert.AreEqual("T arg", this.builder.String);
        }

        [TestMethod]
        public void Test_MultiGenericArgument()
        {
            var type = typeof(ITestGenericMethod);
            var method = type.GetMethod("MixedArguments");

            foreach (var p in method.GetParameters())
            {
                this.builder.Add(p, false);
            }

            Assert.AreEqual("i, arg1, s", this.builder.String);
        }

        [TestMethod]
        public void Test_MultiGenericArgument_WithTypes()
        {
            var type = typeof(ITestGenericMethod);
            var method = type.GetMethod("MixedArguments");

            foreach (var p in method.GetParameters())
            {
                this.builder.Add(p, true);
            }

            Assert.AreEqual("System.Int32 i, T1 arg1, System.String s", this.builder.String);
        }

        [TestMethod]
        public void Test_NestedGenericArguments_WithTypes()
        {
            var type = typeof(ITestGenericMethod);
            var method = type.GetMethod("GenericParameter");

            foreach (var p in method.GetParameters())
            {
                this.builder.Add(p, true);
            }

            Assert.AreEqual("System.Collections.Generic.IEnumerable<T> args", this.builder.String);
        }

        [TestMethod]
        public void Test_ComplexNestedGenericArgumens_WithTypes()
        {
            var type = typeof(ITestNestedGenericArgument<bool>);
            var method = type.GetMethod("Process");

            foreach (var p in method.GetParameters())
            {
                this.builder.Add(p, true);
            }

            Assert.AreEqual("System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<System.Boolean>> items", this.builder.String);
        }
    }
}
